package cn.hbads.version.domain.calendar.listener;

import cn.hbads.version.config.DefaultVersionStrategyConfigProvider;
import cn.hbads.version.config.VersionStrategyConfigProvider;
import cn.hbads.version.domain.calendar.aggregate.VersionCalendar;
import cn.hbads.version.domain.calendar.factory.VersionCalendarFactory;
import cn.hbads.version.domain.calendar.model.DataIdentityModel;
import cn.hbads.version.domain.calendar.persist.repository.IVersionCalendarRepository;
import cn.hbads.version.domain.version.aggregate.DataVersion;
import cn.hbads.version.domain.version.aggregate.DataVersionChain;
import cn.hbads.version.domain.version.event.DataVersionChainEvent;
import cn.hutool.core.collection.CollectionUtil;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * <b> 版本日历监听器 </b>
 *
 * @author : yvvb
 * @date : 2025/5/8
 */
@Component
public class CalendarListener {

    private final VersionStrategyConfigProvider versionStrategyConfigProvider;
    private final VersionCalendarFactory versionCalendarFactory;
    private final IVersionCalendarRepository versionCalendarRepository;

    public CalendarListener(ObjectProvider<VersionStrategyConfigProvider> versionStrategyConfigProvider, VersionCalendarFactory versionCalendarFactory, IVersionCalendarRepository versionCalendarRepository) {
        this.versionStrategyConfigProvider = versionStrategyConfigProvider.getIfAvailable(DefaultVersionStrategyConfigProvider.INSTANCE_SUPPLIER);
        this.versionCalendarFactory = versionCalendarFactory;
        this.versionCalendarRepository = versionCalendarRepository;
    }

    @EventListener
    public <T, E extends DataVersion<T>, C extends DataVersionChain<T, E>> void generateVersionCalendar(DataVersionChainEvent<T, E, C> event) {
        if (!versionStrategyConfigProvider.isEnableCalendar()) {
            return;
        }
        final C dataVersionChain = event.getDataVersionChain();
        final Map<LocalDate, VersionCalendar> dateDataVersionCalenderMap = versionCalendarFactory.batchCreateFromVersionChain(dataVersionChain)
                .unwrapped(errorType -> new RuntimeException(errorType.getErrorMsg()));
        final Collection<E> removedVersions = dataVersionChain.getRemovedVersions();
        if (CollectionUtil.isNotEmpty(removedVersions)) {
            versionCalendarRepository.batchDelete(removedVersions.stream().map(DataIdentityModel::buildFrom).toList());
        }
        versionCalendarRepository.batchSave(new ArrayList<>(dateDataVersionCalenderMap.values()));
    }
}
